Skip to content

feat: add grouped exposure views#624

Merged
Seranged merged 39 commits into
feature/lite-215-convert-vault-page-sections-to-accordion-stylefrom
feature/lite-216-add-open-interest-section-to-vault-page-sankey-style-flow
Jul 1, 2026
Merged

feat: add grouped exposure views#624
Seranged merged 39 commits into
feature/lite-215-convert-vault-page-sections-to-accordion-stylefrom
feature/lite-216-add-open-interest-section-to-vault-page-sankey-style-flow

Conversation

@Seranged

@Seranged Seranged commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Shows grouped live exposure where users compare lend and earn opportunities.
  • Groups duplicate backing assets by underlying collateral so exposure reads as asset concentration while preserving vault-level detail on vault pages.
  • Uses the lend vault Exposure accordion as the combined live/configured exposure surface: configured collateral vaults are shown with live borrow exposure, Max LTV, and Liquidation LTV.
  • Treats incomplete exposure inputs as loading or unavailable instead of rendering zero-valued or idle-only exposure.

Changes

  • Adds a shared collateral open-interest composable backed by the V3 open-interest/by-collateral endpoint so list rows and vault pages use the same cached data.
  • The shared collateral open-interest loader dedupes same-chain requests and ignores stale overlapping chain responses.
  • Sorts collateral exposure groups by active open interest first, then LTV, so the most relevant exposure appears first.
  • Lend rows show compact exposure assets with hover/click breakdowns containing absolute value and percentage share.
  • Lend vault pages show each configured collateral vault with live exposure, Max LTV, and Liquidation LTV in the Exposure section.
  • Lend row collateral exposure previews use the same Live exposure value and LTV ordering as the vault page section.
  • Earn rows show Allocates into as combined collateral exposure with the same compact asset-stack preview pattern.
  • Earn vault pages show strategy-level exposure rows, including current exposure, collateral exposure assets, and caps.
  • Shared exposure display logic keeps idle exposure separate from live collateral exposure, merges duplicate assets by display label, and reports unavailable data when price or live split inputs are missing.
  • Explore Matrix stays scoped to the existing matrix views; a dedicated Open Interest matrix view is deferred.

Visual review guide

Screenshots compare this branch against feature/lite-215-convert-vault-page-sections-to-accordion-style. The after screenshots were refreshed from PR #624 preview head 04e01cf3.

Lend row exposure

Before After
Lend row before Lend row after

Lend row exposure preview

After
Lend row exposure preview after

Lend vault Exposure section

Before After
Lend vault exposure before Lend vault exposure after

Earn row Allocates into

Before After
Earn row before Earn row after

Earn vault Exposure section

Before After
Earn vault exposure before Earn vault exposure after

Test plan

  • npm run test:run -- tests/composables/useCollateralOpenInterest.test.ts tests/utils/open-interest.test.ts tests/utils/vault/collateral-exposure.test.ts tests/server/v3-proxy.test.ts
  • npm run test:run -- tests/utils/vault/exposure-display.test.ts
  • npm run typecheck
  • npx eslint components/entities/vault/VaultItem.vue components/entities/vault/VaultEarnItem.vue components/entities/vault/overview/VaultOverview.vue components/entities/vault/overview/VaultOverviewBlockBorrow.vue components/entities/vault/overview/earn/VaultOverviewEarnBlockExposure.vue composables/useCollateralOpenInterest.ts utils/vault/collateral-exposure.ts
  • npx eslint components/entities/vault/VaultExposureSummary.vue components/entities/vault/VaultItem.vue components/entities/vault/VaultEarnItem.vue components/entities/vault/VaultExposureListModal.vue components/entities/vault/overview/VaultOverviewBlockGeneral.vue components/entities/vault/overview/earn/VaultOverviewEarnBlockStats.vue components/entities/vault/overview/earn/VaultOverviewEarnBlockExposure.vue components/entities/vault/discovery/DiscoveryMarketAttributeMatrix.vue utils/vault/exposure-display.ts tests/utils/vault/exposure-display.test.ts
  • npm run build
  • Browser screenshot smoke on PR feat: add grouped exposure views #624 preview for lend row, lend row exposure preview, lend vault Exposure, earn row, and earn vault Exposure.

@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 08:45 Destroyed
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: euler-xyz/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4f314cd9-38f3-43b9-b1ed-638769e036ee

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/lite-216-add-open-interest-section-to-vault-page-sankey-style-flow

Comment @coderabbitai help to get the list of available commands.

@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 09:01 Destroyed
@railway-app

railway-app Bot commented Jun 25, 2026

Copy link
Copy Markdown

🚅 Deployed to the euler-lite-pr-624 environment in euler-lite

Service Status Web Updated (UTC)
dev-build ✅ Success (View Logs) Web Jun 30, 2026 at 6:06 pm

Polish the vault open interest graph with card-based nodes, responsive mobile stacking, and data-aware spacing for dense collateral sets.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 09:27 Destroyed
Remove the standalone vault-page open interest chart and add a compact Explore matrix Open Interest view grouped by backing asset, including duplicate-vault counts for aggregated exposures.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 11:03 Destroyed
Limit the matrix Open Interest view to the first four borrow-vault cards by default and add a Show more/Show less control for dense markets.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 11:13 Destroyed
Keep every borrow-vault card visible in the matrix Open Interest view, but collapse each card's backing-asset rows after the top three with a per-card Show more control.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 11:27 Destroyed
Center the per-card Show more control in the matrix Open Interest view.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 11:29 Destroyed
Show token avatars next to borrow and backing asset symbols in the matrix Open Interest view.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 12:40 Destroyed
Drops the redundant 'Can be used as collateral' field from vault overview surfaces now that collateral exposure is covered by the matrix/open-interest work.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 14:48 Destroyed
Adds shared backing-asset grouping for exposure data and applies it across lend rows, lend exposure details, earn rows, and earn vault exposure sections.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 15:20 Destroyed
@Seranged Seranged changed the title feat: add vault open interest overview feat: add grouped exposure views Jun 25, 2026
Hides backing-asset group headers when an exposure section only has one backing asset, leaving the underlying vault rows as the primary content.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 15:44 Destroyed
Removes visible backing-asset symbol lists from lend and earn list rows so the compact exposure datapoints stay to count plus token avatars.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 15:52 Destroyed
Flatten collateral and earn exposure detail sections so vault rows render without backing-asset headers. Keep grouped ordering and collapsed show-more behavior, with counts based on hidden rows.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 25, 2026 16:05 Destroyed
Adds a Chart.js doughnut view to the borrow pair overview, using the existing open-interest endpoint and grouped backing-asset model. Includes the total borrowed amount, per-asset percentages, values, and grouped vault counts.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 09:35 Destroyed

@LeonardEulerXYZ LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leonard review — PR #624

Verdict: COMMENT — no blocking findings found on head 80f23665f8aa9ebd291d3ac2e7a5842f9400dfcf. I’m leaving this as a comment rather than approval because approval state was not requested.

Scope reviewed:

  • Grouped collateral exposure/open-interest utilities and tests.
  • Shared useCollateralOpenInterest() loader, stale-chain handling, and V3 proxy allowlist for /v3/evk/vaults/open-interest/by-collateral.
  • Lend vault grouped Collateral exposure UI and borrow-pair Open interest UI on the PR Railway preview.
  • Scalability / maintainability hygiene pass across sibling lend/earn/borrow exposure surfaces.
  • Existing bot/reviewer feedback. CodeRabbit’s visible top-level note says auto-review was skipped; I did not find a material active bot claim to carry forward.

Validation run:

  • npm run test:run -- tests/utils/open-interest.test.ts tests/utils/vault/collateral-exposure.test.ts tests/composables/useCollateralOpenInterest.test.ts tests/server/v3-proxy.test.ts — passed, 30 tests.
  • npm run typecheck — passed.
  • npm run build — passed, warnings only.
  • Browser visual smoke on the PR preview:
    • Desktop /lend/0xba98fC35C9dfd69178AD5dcE9FA29c64554783b5?network=1: expanded Collateral exposure for Sentora PYUSD; live exposure rows rendered with Max LTV / Liquidation LTV and collapsed extra row control.
    • Mobile same route: opened Vault information and expanded Collateral exposure; live exposure rows rendered in the narrow modal layout.
    • Desktop /borrow/0xba98fC35C9dfd69178AD5dcE9FA29c64554783b5/0xAB2726DAf820Aa9270D14Db9B18c8d187cbF2f30?network=1: Open interest surface loaded; by-collateral open-interest API returned 200.

Visual evidence:

Review notes:

  • The two earlier Leonard blockers are resolved in this head: the shared loader now guards stale overlapping chain responses, and the borrow-pair Open interest block uses the shared collateral open-interest path rather than maintaining a duplicate fetch/cache path.
  • The grouped exposure abstraction is in shared utilities with focused unit coverage rather than being embedded as one-off component logic. I checked sibling lend-row, lend-vault, earn-row/earn-vault, and borrow-pair exposure/open-interest consumers; the remaining split is intentional presentation shape, not duplicated business logic.
  • No wallet/signing path was exercised. This pass covered read-only route/API/visual behavior for the grouped exposure surfaces.

kanvgupta and others added 3 commits June 30, 2026 16:53
Avoid duplicate Vue keys when an exposure summary contains separate buckets for the same asset address, such as an active asset and its idle bucket.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 13:29 Destroyed
Treat unavailable exposure pricing and missing live splits as unavailable instead of zero-valued exposure, and add focused formatter coverage.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 13:51 Destroyed

@LeonardEulerXYZ LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leonard review — PR #624

Verdict: REQUEST_CHANGES on head 04e01cf3144457e78a01b69fb56a26d228bab828.

Thanks for the latest pass. The two previous blockers appear resolved: useCollateralOpenInterest now ignores stale overlapping chain loads, and the vault overview open-interest section now uses the shared composable rather than its own direct fetch path.

I found one remaining consistency blocker in the newly-added stats-matrix exposure surface: when a vault is utilized but the API lacks the collateral split, the matrix silently drops that vault from exposureItemsByVault while the global exposure state remains ready. That renders the stats cell as - rather than Unavailable, which makes “data missing” look like “no exposure” for exactly the high-utilization vaults where this feature is most useful. I left the concrete note inline.

Validation performed:

  • npm run test:run -- tests/composables/useCollateralOpenInterest.test.ts tests/utils/vault/exposure-display.test.ts tests/utils/vault/collateral-exposure.test.ts
  • npm run typecheck
  • npm run build
  • Targeted ESLint over PR-changed source/test files ✅
  • Full npm run lint is still blocked by existing repository-wide lint debt outside this PR; targeted lint for the changed files passed.
  • Railway preview browser visual smoke at /lend?network=1 on desktop and mobile ✅: the route loaded real content, the new Exposure column/rows were visible, and no material page error state was observed.

Screenshot evidence:

Scalability / maintainability hygiene pass:

  • Good: the open-interest loader and exposure display/grouping logic are now shared across the card, overview, earn, and modal surfaces, with focused tests around the reusable utilities and stale-load behavior.
  • Remaining issue: the stats matrix adds a sibling consumer with its own per-vault omission behavior for missing collateral splits. That should share the same “missing utilized split => unavailable” display invariant as the other grouped-exposure surfaces, rather than degrading to an empty ready state.

Bot/reviewer feedback pass:

  • I did not find active CodeRabbit findings to verify on the current head.
  • Prior Leonard blockers were rechecked against the current diff and are no longer applicable; no Leonard-owned inline comments were present via the review-comments API to delete.

Smoke coverage: browser visual smoke + mobile smoke on the Railway preview; no wallet/signing smoke, since this PR changes read-only exposure presentation and proxy allowlisting, not transaction construction.

Carry per-vault exposure value state in the stats matrix so missing price or utilized split data renders as unavailable instead of an empty ready exposure.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 14:12 Destroyed
@Seranged Seranged requested a review from LeonardEulerXYZ June 30, 2026 14:19

@LeonardEulerXYZ LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leonard review — PR #624

Verdict: COMMENT — no blocking findings found on head 792e9e748f701863359466eeba03ce0f5d8ea8ef. I’m leaving this as a comment rather than approval because this reviewer request did not explicitly ask for approval state.

Compared against parent branch feature/lite-215-convert-vault-page-sections-to-accordion-style / PR #617. This pass was an incremental re-review of the child delta since my previous blocking review on 04e01cf3144457e78a01b69fb56a26d228bab828; the only new diff is components/entities/vault/discovery/DiscoveryMarketAttributeMatrix.vue.

What changed in this head

  • The stats matrix now carries a per-vault exposure entry with both items and valueState.
  • Missing USD input or missing utilized collateral split now records valueState: 'unavailable' for that vault instead of omitting it from the map.
  • VaultExposureSummary now receives the per-vault state, and matrix cell data-value returns loading / unavailable when the exposure cell is not ready.

This resolves my previous blocker: a utilized vault with a missing collateral split should no longer degrade to an empty ready value (-) merely because the global open-interest loader is ready.

Validation performed

  • git diff --check origin/feature/lite-215-convert-vault-page-sections-to-accordion-style...HEAD — passed.
  • npm run test:run -- tests/composables/useCollateralOpenInterest.test.ts tests/utils/vault/exposure-display.test.ts tests/utils/vault/collateral-exposure.test.ts tests/server/v3-proxy.test.ts — passed, 32 tests.
  • npm run typecheck — passed.
  • Targeted ESLint over the changed stats-matrix/exposure files and related tests — passed.
  • npm run build — passed; existing Vite/Rollup chunk/comment warnings only.
  • Headed Chromium/Xvfb route smoke on the current PR Railway preview:
    • /explore?network=1, KPK/Securitize market expanded, Matrix → Stats selected.
    • Stats matrix rendered with the new Exposure column and exposure cells populated for live assets; no material page errors observed.
  • Malicious/supply-chain scan over the incremental diff: no executable script/workflow/dependency/secret/exfiltration indicators found.

Review notes

  • Prior Leonard blockers were rechecked against the current diff and are resolved.
  • CodeRabbit’s visible comment is still a skipped-review status for the non-default base branch; I found no active CodeRabbit finding to verify.
  • Wallet/signing coverage was not run; this PR remains read-only display/data aggregation work and does not modify transaction construction.

Smoke coverage: browser route/visual smoke on the Railway preview; no wallet/signing smoke.

@LeonardEulerXYZ

LeonardEulerXYZ commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@/tmp/pr624-current-screenshot-comment.md

Moves markets listed links into their own row in the exposure popup so Earn vault users can scan and click listed markets more easily.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 17:48 Destroyed
Omits exposure market source labels when no market route exists, avoiding duplicate non-clickable escrow asset entries in Earn exposure popovers.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 17:54 Destroyed
Adds punctuation and reduces the label gap so exposure market links do not appear offset in the popover.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 17:59 Destroyed
Renders exposure market links as inline units so the first link and commas do not appear separated by extra spacing.
@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 June 30, 2026 18:05 Destroyed

@LeonardEulerXYZ LeonardEulerXYZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leonard review — PR #624

Verdict: COMMENT — no blocking findings found on head 243c4e456a47ced60ecfba3a8187f7f9c915aa0b. I’m leaving this as a comment rather than approval because approval state was not requested.

Compared against parent branch feature/lite-215-convert-vault-page-sections-to-accordion-style / PR #617. This pass focused on the current grouped exposure views, the latest Earn/exposure source behavior, and the previously-reviewed shared loader/matrix invariants.

What I checked

  • PR metadata, current diff, surrounding code, and previous Leonard review artifacts.
  • Existing Leonard comments/reviews and current review-comment API state.
  • Bot/reviewer feedback: CodeRabbit’s visible status remains a skipped-review note for this non-default target; I found no active bot code finding to verify or carry forward.
  • Scalability / maintainability hygiene pass across the sibling grouped-exposure consumers: Lend rows, Lend vault overview, Earn rows, Earn vault overview/stats/exposure, Borrow pair open-interest, and Explore matrix stats.

Validation performed

  • npm run test:run -- tests/components/base/BaseExposureSourcesModal.test.ts tests/components/entities/vault/overview/VaultOverviewEarnBlockStats.test.ts tests/utils/vault/exposure-display.test.ts — passed for the matching focused suite that Vitest selected, 6 tests.
  • npm run typecheck — passed.
  • npm run build — passed, warnings only.
  • Headed Chromium/Xvfb browser visual smoke on the current PR build:
    • Desktop /earn?network=1: expanded Euler Prime and opened the Exposure modal; grouped exposure rows and Markets listed links rendered.
    • Mobile /earn?network=1 at 390px width: opened the same Exposure modal; narrow layout kept exposure rows and source links visible without blank/loading/error state.
    • Desktop /explore?network=1: expanded the Securitize/KPK market, selected Matrix + Stats, and verified the Exposure column/cells render.

Visual evidence

I updated the existing Leonard screenshot-evidence comment with verified raw PNG links for this head:
#624 (comment)

Review notes

  • Prior Leonard blockers were rechecked against the current diff and remain resolved: the shared collateral-open-interest loader has stale-load protection, and sibling consumers now use the shared exposure/open-interest path rather than the earlier duplicate fetch/cache shape.
  • The grouped exposure abstraction remains mostly in shared utilities/composables with focused tests, which is the right direction for this surface.
  • I left one non-blocking inline maintainability note on the repeated Earn strategy source helper. The current behavior appears safe enough for merge, but the helper is now duplicated across three Earn exposure components and the !marketKey branch silently drops an otherwise displayable source label. If that is intentional, fine; otherwise it is a tidy candidate for a shared helper/test.

Smoke coverage: browser visual smoke + mobile smoke; no wallet/signing smoke, since this PR changes read-only exposure presentation and proxy/data plumbing, not transaction construction.

Comment lifecycle: updated the existing Leonard screenshot-evidence comment for the current head; no Leonard-owned inline review comments were present to delete; submitted this fresh formal review for the current head.

}
const getStrategyMarketSource = (strategyVault: EVault) => {
const marketKey = getProductKeyByVault(strategyVault.address)
if (!marketKey) return undefined

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking maintainability note: this same getStrategyMarketSource helper is now repeated across the Earn row, Earn stats, and Earn exposure components. The helper also drops the source entirely when getProductKeyByVault() has no route key, even though the exposure sources modal can render a non-linked source label. If suppressing unlinked sources is intentional, fine; otherwise consider extracting a shared helper that always returns the label and conditionally adds to, with a small linked-vs-unlinked strategy test. Neat little branch, but it would like a single home.

@railway-app railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-624 July 1, 2026 10:10 Destroyed
@Seranged Seranged merged commit d6977ef into feature/lite-215-convert-vault-page-sections-to-accordion-style Jul 1, 2026
1 of 2 checks passed
@Seranged Seranged deleted the feature/lite-216-add-open-interest-section-to-vault-page-sankey-style-flow branch July 1, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants